﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace CommunityToolkitMvvmDemo.UserControls
{
    public class EditComboBox : ComboBox
    {
        private bool t = true;             // 首次获取焦点标志位
        private string editText = "";   // 编辑文本内容

        // 数据源绑定List，用于组合框中显示的数据
        private ObservableCollection<object> bindingList = new ObservableCollection<object>(); 

        // 注册依赖属性
        public static readonly DependencyProperty MyItemsSourceProperty =
            DependencyProperty.Register("MyItemsSource",  // 包装器名称
                                                    typeof(IEnumerable),
                                                    typeof(EditComboBox),
                                                    new FrameworkPropertyMetadata(new PropertyChangedCallback(ValueChanged)));

        // 数据源改变，添加数据源到绑定数据源；给 bindingList 赋值，以便于在 后面执行的 OnInitialized 方法中使用
        private static void ValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            EditComboBox ecb = d as EditComboBox;
            ecb.bindingList.Clear();
            foreach (var item in ecb.MyItemsSource)
            {
                ecb.bindingList.Add(item);
            }
        }

        // 设置或获取ComboBox的数据源
        public IEnumerable MyItemsSource  // 包装器
        {
            get
            {
                return (IEnumerable)GetValue(MyItemsSourceProperty);
            }
            set
            {
                if (value == null)
                    ClearValue(MyItemsSourceProperty);
                else
                    SetValue(MyItemsSourceProperty, value);
            }
        }

        // 重写 - 初始化
        protected override void OnInitialized(EventArgs e)
        {
            base.OnInitialized(e);

            this.IsEditable = true;
            this.IsTextSearchEnabled = false;
            this.ItemsSource = bindingList;
        }

        // 重写 - 组合框关闭，数据源恢复
        protected override void OnDropDownClosed(EventArgs e)
        {
            base.OnDropDownClosed(e);

            if (MyItemsSource == null)
                return;

            foreach (var item in MyItemsSource)
            {
                if (!bindingList.Contains(item))
                    bindingList.Add(item);
            }
        }

        // 重写 - 下拉框获取焦点，首次搜索文本编辑框；当焦点从其他控件切换回来时
        protected override void OnGotFocus(RoutedEventArgs e)
        {
            if (t)
                FindTextBox(this);
            else
                t = false;
        }

        // 搜索编辑文本框，添加文本改变事件
        private void FindTextBox(DependencyObject obj)
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                if (child != null && child is TextBox)
                {
                    (child as TextBox).TextChanged += EditComboBox_TextChanged;   // 注册文本改变事件
                }
                else
                {
                    FindTextBox(child);
                }
            }
        }

        // 文本改变，动态控制下拉条数据源
        private void EditComboBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            TextBox tb = sender as TextBox;
            if (tb.IsFocused)
            {
                this.IsDropDownOpen = true;
                if (editText == this.Text)
                    return;

                editText = this.Text;
                SetList(editText);
            }
        }

        // 过滤符合条件的数据项，添加到数据源项中
        private void SetList(string txt)
        {
            if (MyItemsSource == null)
                return;

            try
            {
                string temp1 = ""; 
                string temp2 = "";
                foreach (var item in MyItemsSource)
                {
                    temp1 = item.GetType().GetProperty(this.DisplayMemberPath).GetValue(item, null).ToString();

                    if (string.IsNullOrEmpty(this.SelectedValuePath))
                    {
                        temp2 = "";
                    }
                    else
                    {
                        temp2 = item.GetType().GetProperty(this.SelectedValuePath).GetValue(item, null).ToString();
                    }

                    if (temp1.Contains(txt) || temp2.StartsWith(txt)) // 匹配到 文本框中的值
                    {
                        if (!bindingList.Contains(item))
                            bindingList.Add(item);
                    }
                    else if (bindingList.Contains(item)) // 没有匹配到 文本框中的值，从bindingList 中清除
                    {
                        bindingList.Remove(item);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
    }
}
